package controllers

import (
	"encoding/json"
	"ginjwt/config"
	"ginjwt/models"
	"ginjwt/utils"
	"net/http"

	"github.com/gin-gonic/gin"
)

// 提供用户名和密码，获取access token和refresh token
func JWTCreate(c *gin.Context) {
	conf := config.GetConfig()

	/*
		var user models.User
		if err := c.ShouldBindJSON(&user); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
	*/

	data, err := c.GetRawData()

	if err != nil {
		c.AbortWithStatus(http.StatusBadRequest)
		return
	}

	// 用户传来空数据
	if len(data) == 0 {
		c.JSON(http.StatusBadRequest, gin.H{
			"username": "该字段不能为空",
			"password": "该字段不能为空",
		})
		return
	}

	// 对用户传来的JSON数据解码
	var user models.User
	if err := json.Unmarshal(data, &user); err != nil {
		// 如果用户传过来的JSON数据是{"username": true}会报错
		c.JSON(http.StatusBadRequest, gin.H{
			"detail": "无效数据",
		})
		return
	}

	emptyErrors := gin.H{}

	// username字段可能没有传，或者有该字段但是值为空
	if user.Username == "" {
		emptyErrors["username"] = "该字段必填，且值不能为空"
	}

	// password字段可能没有传，或者有该字段但是值为空
	if user.Password == "" {
		emptyErrors["password"] = "该字段必填，且值不能为空"
	}

	if user.Username == "" || user.Password == "" {
		c.JSON(http.StatusBadRequest, emptyErrors)
		return
	}

	// TOOD:应该从数据库中获取该用户信息
	if user.Username == conf.GetString("AUTH.USERNAME") && user.Password == conf.GetString("AUTH.PASSWORD") {
		// 这里产生access和refresh token
		access := utils.GetAccessToken(user.Username)
		refresh := utils.GetRefreshToken(user.Username)
		c.JSON(http.StatusOK, gin.H{"access": access, "refresh": refresh})
	} else {
		// 401
		c.JSON(http.StatusUnauthorized, gin.H{"detail": "用户名或者密码错误"})
	}
}

// 发送POST请求，请求体中包含refresh token信息，重新获取access token
func JWTRefresh(c *gin.Context) {

	data, err := c.GetRawData() // []uint8

	if err != nil {
		c.AbortWithStatus(http.StatusBadRequest)
		return
	}

	// 用户传来空数据
	if len(data) == 0 {
		c.JSON(http.StatusBadRequest, gin.H{
			"refresh": "该字段不能为空",
		})
		return
	}

	var result map[string]string
	if err := json.Unmarshal(data, &result); err != nil {
		c.AbortWithStatus(http.StatusBadRequest)
		return
	}

	tokenString, ok := result["refresh"]

	if !ok {
		c.JSON(http.StatusBadRequest, gin.H{
			"refresh": "该字段不能为空",
		})
		return
	}

	if tokenString == "" {
		c.JSON(http.StatusBadRequest, gin.H{
			"detail": "refresh字段值不能为空",
		})
		return
	}

	token, err := utils.ValidateToken(tokenString)

	if token != nil && token.Valid {

		claims := token.Claims.(*models.AuthClaims)

		// token类型不匹配
		if claims.TokenType != "refresh" {
			c.JSON(http.StatusUnauthorized, gin.H{"detail": "token类型不匹配"})
			return
		}

		// 生成新的access token 并发送回去
		access := utils.GetAccessToken(claims.UserId)
		c.JSON(http.StatusOK, gin.H{"access": access})

	} else {
		// 这里可能出现的错误
		// 1.token过期
		// 2.token格式不正确
		// 3.token格式正确，但是某个字符出现更改
		c.JSON(http.StatusUnauthorized, gin.H{"detail": err.Error()})
	}
}
